package com.inkyi.assistant.app.notepad;

import com.formdev.flatlaf.util.StringUtils;
import com.inkyi.assistant.app.base.InitValue;
import com.inkyi.assistant.app.component.rsyntax.RSyntaxTextConfig;
import com.inkyi.assistant.app.component.rsyntax.RSyntaxTextEditor;
import com.inkyi.assistant.app.notepad.entity.NoteBaseData;
import com.inkyi.assistant.app.notepad.event.EditorSaveListener;
import com.inkyi.framework.common.utils.BeanUtils;
import com.inkyi.framework.common.utils.EmptyHelper;
import com.inkyi.framework.common.utils.JsonUtils;
import com.inkyi.framework.docdb.*;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * 上下文
 *
 * @author lihongkun
 * @date 2024/11/23
 */
public class NoteContext {

    public static final DocDataSource DATA_SOURCE;

    public static InitValue<NoteContentPanel> noteContentPanel = new InitValue<>();

    public static InitValue<NoteListingsPanel> noteListingsPanel = new InitValue<>();

    static {
        DocDataSourceBuilder dsBuilder = new DocDataSourceBuilder();
        dsBuilder.setRootPath(System.getProperty("user.home") + "/InkStore/");
        dsBuilder.setDataSourceId("notepad");
        dsBuilder.setDataSourceName("记事本");
        dsBuilder.setIdType(DocConstant.ID_TYPE_DATE);
        DATA_SOURCE = dsBuilder.build();
    }

    public static NoteListingsPanel getNoteListingsPanel() {
        return noteListingsPanel.getValue();
    }

    public static NoteContentPanel getNoteContentPanel() {
        return noteContentPanel.getValue();
    }


    public static RSyntaxTextEditor createRSyntaxTextEditor(NoteBaseData data) {
        DocRecord docRecord = NoteContext.DATA_SOURCE.findById(data.getId());
        if (docRecord == null || !NodeDataType.NODE_DOCUMENT.getKey().equals(docRecord.getType())) {
            return null;
        }
        // 内容
        String dataContent = "";
        RSyntaxTextConfig editConfig = new RSyntaxTextConfig();
        List<DocRecord> children = docRecord.getChildren();
        if (children != null && !children.isEmpty()) {
            dataContent = (String) children.get(0).getData();
        }
        // 配置
        try {
            DocProperties properties = docRecord.getProperties();
            editConfig = BeanUtils.mapToBean(properties, RSyntaxTextConfig.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        RSyntaxTextEditor editor = new RSyntaxTextEditor();
        editor.setContent(data.getTitle());
        editor.setId(data.getId());
        editor.setContent(dataContent);
        editor.setEditConfig(editConfig);
        editor.addListener(new EditorSaveListener());
        return editor;
    }

    /**
     * 创建记事本
     *
     * @param title 标题
     * @return {@link DocRecord }
     */
    public static DocRecord createNotepad(String title) {
        return NoteContext.createNewDoc(title, NodeDataType.NODE_NOTEPAD.getKey());
    }

    public static DocRecord createDocument(String title) {
        return NoteContext.createNewDoc(title, NodeDataType.NODE_DOCUMENT.getKey());
    }

    public static DocRecord createDocument() {
        return NoteContext.createNewDoc(null, NodeDataType.NODE_DOCUMENT.getKey());
    }

    public static DocRecord createNewDoc(String title, String type) {
        DocProperties properties = new DocProperties();
        properties.setCreateTime(String.valueOf(System.currentTimeMillis()));
        properties.setUpdateTime(String.valueOf(System.currentTimeMillis()));
        if (EmptyHelper.isEmpty(title)) {
            properties.setTitle("新" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()));
        } else {
            properties.setTitle(title);
        }
        DocRecord record = new DocRecord();
        record.setType(type);
        record.setProperties(properties);
        return record;
    }


    public static List<DocRecord> findDataAll() {
        List<DocRecord> roots = new ArrayList<>();
        File dataFile = new File(DATA_SOURCE.getDataSourcePath());
        try {
            File[] files = dataFile.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    return name.endsWith(".json");
                }
            });
            for (File file : files) {
                DocRecord nodeDataRecord = handleNodeData(file);
                roots.add(nodeDataRecord);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return roots;

    }

    private static DocRecord handleNodeData(File file) throws IOException {
        if (file == null || !file.exists() || !file.isFile()) {
            return null;
        }
        // 传进来的是一个文件，找文件同级目录。
        String fileString = Files.readString(file.toPath(), StandardCharsets.UTF_8);
        if (StringUtils.isEmpty(fileString)) {
            return null;
        }
        DocRecord dataRecord = JsonUtils.parseObject(fileString, DocRecord.class);
        if (dataRecord == null) {
            return null;
        }
        // 同级目录是否存在
        String filePath = file.getAbsolutePath();
        String dirPath = filePath.substring(0, filePath.lastIndexOf("."));
        File dirFile = new File(dirPath);
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return dataRecord;
        }
        File[] childFiles = dirFile.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".json");
            }
        });
        if (childFiles == null || childFiles.length == 0) {
            return dataRecord;
        }
        List<DocRecord> childList = new ArrayList<>();
        for (File childFile : childFiles) {
            DocRecord childRecord = handleNodeData(childFile);
            childList.add(childRecord);
        }
        dataRecord.setChildren(childList);
        return dataRecord;
    }
}
